package com.hooya.fa.eu.biz.dao.manager;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateRange;
import cn.hutool.core.date.DateTime;
import com.alibaba.excel.EasyExcel;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.hooya.fa.eu.api.util.DateExtUtil;
import com.hooya.fa.eu.api.util.FileUtil;
import com.hooya.fa.eu.api.vo.SaleRelationVO;
import com.hooya.fa.eu.api.vo.XsReportInfoVO;
import com.hooya.fa.eu.biz.dao.entity.eu.his.TempJcjl;
import com.hooya.fa.eu.biz.dao.entity.eu.his.TempPkpy;
import com.hooya.fa.eu.biz.dao.entity.eu.his.TempXsjl;
import com.hooya.fa.eu.biz.dao.entity.eu.his.TempZyjl;
import com.hooya.fa.eu.biz.service.OrderEuService;
import com.hooya.integrated.common.core.util.BeanCopyUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.hooya.fa.eu.api.constant.FileNameConstant.EU_SALE_FOLDER_NAME;

/**
 * @Description 1
 * @Author : Zongz
 * @Copyright Copyright (c) 豪雅集团
 * @Create 2024/4/28
 * @Version 1.0.0
 */
@Slf4j
@Component
@DS("fa_eu_his")
@AllArgsConstructor
public class EuHisSaleManager {

    private final OrderEuService orderEuService;

    /**
     * 生成销售相关信息的月度报表
     *
     * @param startDate     开始时间
     * @param endDate       结束时间
     * @param initJcMap     进仓数据
     * @param xsDateMap     销售数据
     * @param zyList
     * @param pyList        盘盈数据
     * @param invoiceNoList
     */
    public void genMonthSaleReport(String startDate, String endDate, List<TempJcjl> jcjlList,
                                   Map<String, List<TempJcjl>> initJcMap, Map<String, List<TempXsjl>> xsDateMap,
                                   List<TempZyjl> zyList, List<TempPkpy> pyList, Map<Integer, String> invoiceNoList) {
        List<SaleRelationVO> res = new LinkedList<>();
        //处理数据
        Date start = new Date(startDate.replace("-", "/"));
        Date end = new Date(endDate.replace("-", "/"));
        DateRange dateRange = DateExtUtil.range(start, end, DateField.DAY_OF_MONTH);
        for (DateTime time : dateRange) {
//            long ss = System.currentTimeMillis();
            String curDate = time.toDateStr();
            if (curDate.equals(endDate)) {
                continue;
            }
            //当日进仓、合并
            Map<String, List<TempJcjl>> curJcMap = jcjlList.stream()
                    .filter(l -> StringUtils.isNotBlank(l.getHtrq()) && l.getHtrq().equals(curDate))
                    .collect(Collectors.groupingBy(l -> l.getCpbh() + l.getPlace()));
            curJcMap.forEach((k, l) -> {
                List<TempJcjl> jcList = initJcMap.get(k);
                if (CollectionUtils.isEmpty(jcList)) {
                    initJcMap.put(k, l);
                } else {
                    jcList.addAll(l);
                    initJcMap.put(k, jcList);
                }
            });
            //当日转运、合并
            List<TempZyjl> curZyList = zyList.stream().filter(l -> l.getHtrq().equals(curDate)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(curZyList)) {
                for (TempZyjl zy : curZyList) {
                    //减转出，加转入
                    String zlKey = zy.getCpbh() + zy.getZlck();
                    String zcKey = zy.getCpbh() + zy.getZcck();
                    TempJcjl zlJc = BeanCopyUtils.copyPropertiesNew(zy, TempJcjl::new, (s, t) -> {
                        t.setBelongs(s.getToBelongs());
                        t.setPlace(s.getZlck());
                    });
                    List<TempJcjl> zlJcList = initJcMap.get(zlKey);
                    if (CollectionUtils.isEmpty(zlJcList)) {
                        List<TempJcjl> list = new LinkedList<>();
                        list.add(zlJc);
                        initJcMap.put(zlKey, list);
                    } else {
                        //有就直接往里塞，不合并
                        zlJcList.add(zlJc);
                        initJcMap.put(zlKey, zlJcList);
                    }
                    List<TempJcjl> zcJcList = initJcMap.get(zcKey);
                    // 转出数据没有的话不管，直接扔掉
                    if (!CollectionUtils.isEmpty(zcJcList)) {
                        zcJcList.stream().filter(l -> l.getBelongs().equals(zy.getFromBelongs()))
                                .forEach(l -> l.setSl(Math.max(0, l.getSl() - zy.getSl())));
                        //重新赋值
                        initJcMap.put(zcKey, zcJcList);
                    } else {
                        log.error(zcKey + ":库存不存在");
                    }
                }
            }
            //当日销售
            List<TempXsjl> curXsList = xsDateMap.get(curDate);
            if (CollectionUtils.isEmpty(curXsList)) {
                continue;
            }
            List<String> sheetNumberList = curXsList.stream().map(TempXsjl::getSheetNumber).collect(Collectors.toList());
            List<XsReportInfoVO> otherInfoList = orderEuService.getXsReportInfoList(sheetNumberList);
            List<String> infoSheetNumberList = otherInfoList.stream()
                    .map(XsReportInfoVO::getSheetNumber).collect(Collectors.toList());
            sheetNumberList.removeAll(infoSheetNumberList);
            if (!CollectionUtils.isEmpty(sheetNumberList)) {
                List<XsReportInfoVO> supplementList = orderEuService.getXsReportInfoOtherList(sheetNumberList);
                otherInfoList.addAll(supplementList);
            }
            Map<String, XsReportInfoVO> xsOtherInfoMap = otherInfoList.stream()
                    .collect(Collectors.toMap(XsReportInfoVO::getSheetNumber, i -> i));
            for (TempXsjl xs : curXsList) {
                String key = xs.getCpbh() + xs.getChck();
                //销售数量
                int xsNum = xs.getSl();
                List<TempJcjl> curJc = initJcMap.get(key);
                if (!CollectionUtils.isEmpty(curJc)) {
                    //按照时间顺序排序
                    List<TempJcjl> curJcList = curJc.stream().filter(l -> l.getSl() != 0)
                            .sorted(Comparator.comparing(TempJcjl::getHtrq)).collect(Collectors.toList());
                    for (TempJcjl jc : curJcList) {
                        //仓库剩余数量
                        int leftNum = jc.getSl() - xsNum;
                        //本次销售数量
                        int num = leftNum < 0 ? jc.getSl() : xs.getSl();
                        //更新销售数量
                        xsNum = leftNum > 0 ? 0 : Math.abs(leftNum);
                        xs.setSl(xsNum);
                        //测试检查数量
                        jc.setSl(Math.max(0, leftNum));
                        genSaleRelation(num, Math.max(0, leftNum), xsOtherInfoMap, jc, xs, res, invoiceNoList);
                        if (xsNum == 0) {
                            break;
                        }
                    }
                }
                //所有进仓不够减扣，先从盘亏盘盈扣
                if (xsNum > 0) {
                    //先看盘盈是否还有
                    List<TempPkpy> py = pyList.stream().filter(l -> l.getCpbh().equals(xs.getCpbh())
                            && l.getPlace().equals(xs.getChck()) && l.getDate().equals(xs.getOrderDate())
                            && l.getSl() > 0).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(py)) {
                        // 一般对应日期只有一个
                        for (TempPkpy data : py) {
                            TempJcjl jc = BeanCopyUtils.copyPropertiesNew(data, TempJcjl::new);
                            int outNum = xsNum - data.getSl() > 0 ? data.getSl() : xsNum;
                            int finalXsNum = xsNum;
                            //在数量变化前，先确定剩余销售数量
                            xsNum = Math.max(0, xsNum - data.getSl());
                            pyList.stream().filter(l -> l.getId().equals(data.getId()))
                                    .forEach(l -> l.setSl(finalXsNum - l.getSl() > 0 ? 0 : Math.abs(finalXsNum - l.getSl())));
                            genSaleRelation(outNum, 0, xsOtherInfoMap, jc, xs, res, invoiceNoList);
                        }
                    }
                    if (xsNum > 0) {
                        //-1表示就是说明，仓库已经为0，但销售数量还有的情况下；上面的正常情况都是将仓库扣减到0为止
                        genSaleRelation(xsNum, -1, xsOtherInfoMap, null, xs, res, invoiceNoList);
//                    log.info("sheetNumber: " + xs.getSheetNumber() + ",sku: " + xs.getCpbh() +
//                            ",仓库: " + xs.getChck() + ",还剩余[" + xsNum +  "]个无处减扣");
                    }

                }
            }
        }
        //生成报表
        EasyExcel.write(FileUtil.getExcelPath() + EU_SALE_FOLDER_NAME + "sale_" +
                        startDate.substring(2, 7).replace("-", ".") + "-" +
                        endDate.substring(2, 7).replace("-", ".") + ".xlsx", SaleRelationVO.class)
                .sheet("sale").doWrite(res);
    }

    /**
     * 生成结果
     *
     * @param outNum         销售数量
     * @param leftNum        仓库剩余数量
     * @param xsOtherInfoMap 销售sheetNumber对应客户信息
     * @param jc             进仓数据
     * @param xs             销售数据
     * @param res            最终结果集
     * @param invoiceNoList
     */
    private void genSaleRelation(Integer outNum, Integer leftNum, Map<String, XsReportInfoVO> xsOtherInfoMap,
                                 TempJcjl jc, TempXsjl xs, List<SaleRelationVO> res, Map<Integer, String> invoiceNoList) {
        SaleRelationVO vo = BeanCopyUtils.copyPropertiesNew(xs, SaleRelationVO::new, (s, t) -> t.setPlace(s.getChck()));
        vo.setOutNum(outNum);
        vo.setLeftNum(leftNum);
        if (Objects.nonNull(jc)) {
            vo.setInvoiceNo(jc.getHthm());
//            vo.setBelongs(jc.getBelongs());
        }
        if (StringUtils.isNotBlank(invoiceNoList.get(xs.getId()))) {
            vo.setLocalInvoiceNo(invoiceNoList.get(xs.getId()));
        }
        XsReportInfoVO otherInfo = xsOtherInfoMap.get(xs.getSheetNumber());
        if (Objects.nonNull(otherInfo)) {
            vo.setWxdj(otherInfo.getPrice());
            vo.setTrackNo(otherInfo.getTrackNo());
            vo.setCusName(otherInfo.getCustomer());
            vo.setAddress(otherInfo.getAddress());
            vo.setZip(otherInfo.getPostcode());
            vo.setPhone(otherInfo.getPhone());
//        } else {
//            log.info("[" + xs.getSheetNumber() + "]没有客户信息");
        }
        res.add(vo);
    }

}
